//===========================================
// Function : Synchronous read write RAM
// Coder    : Deepak Kumar Tala
// Date     : 1-Nov-2005
//===========================================
module ram_dp_sr_sw #(parameter DATA_WIDTH = 8,
                  parameter ADDR_WIDTH = 8,
                  parameter RAM_DEPTH = (1 << ADDR_WIDTH))(
input  wire                  clk       , // Clock Input
input  wire [ADDR_WIDTH-1:0] address_0 , // address_0 Input
inout  wire [DATA_WIDTH-1:0] data_0    , // data_0 bi-directional
input  wire                  cs_0      , // Chip Select
input  wire                  we_0      , // Write Enable/Read Enable
input  wire                  oe_0      , // Output Enable
input  wire [ADDR_WIDTH-1:0] address_1 , // address_1 Input
inout  wire [DATA_WIDTH-1:0] data_1    , // data_1 bi-directional
input  wire                  cs_1      , // Chip Select
input  wire                  we_1      , // Write Enable/Read Enable
input  wire                  oe_1        // Output Enable
); 
//--------------Internal variables---------------- 
reg [DATA_WIDTH-1:0] data_0_out ; 
reg [DATA_WIDTH-1:0] data_1_out ;
// Use Associative array to save memory footprint
typedef reg [ADDR_WIDTH-1:0] mem_addr;
reg [DATA_WIDTH-1:0] mem [mem_addr];

//--------------Code Starts Here------------------ 
// Memory Write Block 
// Write Operation : When we_0 = 1, cs_0 = 1
always @ (posedge clk)
begin : MEM_WRITE
  if ( cs_0 && we_0 ) begin
     mem[address_0] = data_0;
  end else if (cs_1 && we_1) begin 
     mem[address_1] = data_1;
  end
end

// Tri-State Buffer control 
// output : When we_0 = 0, oe_0 = 1, cs_0 = 1
assign data_0 = (cs_0 && oe_0 && !we_0) ? data_0_out : 8'bz; 

// Memory Read Block 
// Read Operation : When we_0 = 0, oe_0 = 1, cs_0 = 1
always @ (posedge clk)
begin : MEM_READ_0
  if (cs_0 && !we_0 && oe_0) begin
    data_0_out = mem[address_0]; 
  end else begin
    data_0_out = 0; 
  end  
end 

//Second Port of RAM
// Tri-State Buffer control 
// output : When we_0 = 0, oe_0 = 1, cs_0 = 1
assign data_1 = (cs_1 && oe_1 && !we_1) ? data_1_out : 8'bz; 
// Memory Read Block 1 
// Read Operation : When we_1 = 0, oe_1 = 1, cs_1 = 1
always @ (posedge clk)
begin : MEM_READ_1
  if (cs_1 && !we_1 && oe_1) begin
    data_1_out = mem[address_1]; 
  end else begin
    data_1_out = 0;
  end
end

endmodule // End of Module ram_dp_sr_sw
